package com.gxitsky.async.design.controller;

import com.gxitsky.async.design.listener.ServletAsyncListener;
import com.gxitsky.async.design.service.MessageService;
import com.gxitsky.async.design.task.Work;
import com.gxitsky.utils.DateUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.AsyncContext;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Date;

/**
 * @author gxing
 * @desc TODO
 * @date 2022/7/25
 */
@RestController
@RequestMapping("/asyncServlet")
public class AsyncServletController extends BaseController {

    @Autowired
    private MessageService messageService;

    @GetMapping("/asyncContext4")
    public void asyncContext4(HttpServletRequest servletRequest) {
        handler(servletRequest, () -> messageService.detail());
    }

    @GetMapping("/asyncContext3")
    public void asyncContext3(HttpServletRequest servletRequest) {
        String s = RandomStringUtils.randomNumeric(4);
        System.out.println(s + ":接收请求线程开始:" + Thread.currentThread().getName() + ";" + DateUtil.format(new Date(), DateUtil.PATTERN_YMDHMS_SLASH));
        AsyncContext asyncContext = servletRequest.startAsync();
        asyncContext.start(() -> new Thread(new Work(asyncContext)).start());
        System.out.println(s + ":接收请求线程结束," + DateUtil.format(new Date(), DateUtil.PATTERN_YMDHMS_SLASH));
    }

    /**
     * @param servletRequest 请求
     * @desc 响应, 注意：异步响应,是 Controller 方法里一定要显式入参 response,否则会报错,且此错比较怪异
     * 个人理解, 方法是 void 无返回值,显示入参了 response,
     * Spring MVC则不会自动处理响应,表示由开发者使用 Response响应
     * 参考：https://spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-servlet-3-async-support
     * 参考：http://codingjunkie.net/jee-6-and-spring-mvc/
     * @desc TODO
     * @author gxing
     * @date 2022/7/25
     */
    @GetMapping("/asyncContext2")
    public void asyncContext2(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
        String s = RandomStringUtils.randomNumeric(4);
        System.out.println(s + ":接收请求线程开始:" + Thread.currentThread().getName() + ";" + DateUtil.format(new Date(), DateUtil.PATTERN_YMDHMS_SLASH));
//        try {
//            servletResponse.getWriter().println("Hello");
//            System.out.println(Thread.currentThread().getName() + ": 睡眠8秒");
//            Thread.sleep(8000);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
        AsyncContext asyncContext = servletRequest.startAsync();
        new Thread(() -> {
            System.out.println(s + ":异步线程启动:" + Thread.currentThread().getName());
            PrintWriter writer = null;
            try {
                asyncContext.setTimeout(10000);
                asyncContext.addListener(new ServletAsyncListener());
                Thread.sleep(8000);
                ServletResponse response = asyncContext.getResponse();
                response.setContentType("application/json;charset=UTF-8");
                writer = response.getWriter();
//                HashMap<String, Object> map = new HashMap<>();
//                map.put("id", 100L);
//                map.put("message", "Hello World!");
//                writer.println(JSON.toJsonString(map));
                writer.println("Hello");
                asyncContext.complete();
                System.out.println(s + ":异步线程结束;" + DateUtil.format(new Date(), DateUtil.PATTERN_YMDHMS_SLASH));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        System.out.println(s + ":接收请求线程结束," + DateUtil.format(new Date(), DateUtil.PATTERN_YMDHMS_SLASH));
    }

    /**
     * @param request 请求
     * @desc 异步测试
     * @author gxing
     * @date 2022/7/28 16:56
     */
    @RequestMapping(value = "/asyncContext1", method = RequestMethod.GET)
    public void asyncContext1(HttpServletRequest request) {
        System.out.println("接收请求线程开始:" + Thread.currentThread().getName());
        AsyncContext asyncContext = request.startAsync();
        new Thread(new Work(asyncContext)).start();
        System.out.println("接收请求线程结束");
    }
}

